package com.hitqz.robot.driver;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.RateLimiter;
import com.hitqz.robot.api.business.enums.*;
import com.hitqz.robot.api.common.dto.form.FormConfigDto;
import com.hitqz.robot.api.common.dto.form.FormFieldConfigDto;
import com.hitqz.robot.api.common.dto.robot.DoorStatusDto;
import com.hitqz.robot.api.common.dto.robot.InitPosDto;
import com.hitqz.robot.api.common.dto.robot.RobotGoTargetPosDto;
import com.hitqz.robot.api.common.dto.robot.RobotMoveDto;
import com.hitqz.robot.api.common.entity.Robot;
import com.hitqz.robot.api.common.entity.RobotMap;
import com.hitqz.robot.api.common.entity.RobotMapPos;
import com.hitqz.robot.common.core.util.R;
import com.hitqz.robot.driver.dto.KcLocationDto;
import com.hitqz.robot.driver.dto.KcRobotRunningStatus;
import com.hitqz.robot.driver.dto.KcStopStatusDto;
import com.hitqz.robot.driver.dto.robot.RobotCustomInfo;
import com.hitqz.robot.driver.dto.robot.RobotParamsDto;
import com.hitqz.robot.driver.model.IRobotPosDto;
import com.hitqz.robot.driver.model.MapAttributesDto;
import com.hitqz.robot.driver.model.PointDto;
import com.hitqz.robot.driver.parent.RobotDriverService;
import com.hitqz.robot.driver.util.*;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Polygon;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wengyx
 * @date 2023/8/20
 */
@Slf4j
@Service("robotDriverService")
public class KcRobotDriverImpl implements RobotDriverService {


    private static float speed = 0.2f;

    private static float minSpeed = 0.05f;

    private static float maxSpeed = 1.2f;

    private static final DecimalFormat df = new DecimalFormat("0.00");
    private static final DecimalFormat df_2 = new DecimalFormat("0.0");

    private static final RateLimiter goHomeLimiter = RateLimiter.create(1);

    /**
     * 创建科聪udp客户端
     *
     * @param robot 机器人实体类
     * @return true/false
     */
    @Override
    public boolean doOnlineMode(Robot robot) {
        boolean result = false;
        try {
            KcToolkit.robot = robot;
            result = KcToolkit.init(robot.getIpAddress());
        } catch (Exception e) {
            log.error("[kc] doOnlineMode error", e);
        }
        log.info("[kc] doOnlineMode success");
        return result;
    }

    @Override
    public boolean setSpeed(RobotMoveDto baseSpeedDto) {
        KcCacheUtil.setSpeedFlag();
        String linerXSpeed = String.valueOf(speed);
        String linerYSpeed = String.valueOf(speed);
        String angularSpeed = "0.2";
        boolean lineXResult = true;
        boolean lineYResult = true;
        boolean angleResult = true;
        if (StrUtil.isNotBlank(baseSpeedDto.getLinerSpeed()) && Objects.equals(baseSpeedDto.getLinerSpeedY(), "0")) {
            //摇杆取值
            if (baseSpeedDto.isRocker()) {
                float rockerSpeed = Math.abs(Float.parseFloat(baseSpeedDto.getLinerSpeed()));
                linerXSpeed = String.valueOf(Math.min(Float.parseFloat(linerXSpeed), rockerSpeed));
            }
            //符号
            linerXSpeed = baseSpeedDto.getLinerSpeed().contains("-") ? "-" + linerXSpeed : linerXSpeed;
            linerXSpeed = Objects.equals(baseSpeedDto.getLinerSpeed(), "0") ? "0" : linerXSpeed;
            lineXResult = KcToolkit.writeVar("cmd_vel_line_x", DataTypeEnum.REAL, linerXSpeed);
            log.info("[kc] set line x speed {} m/s", linerXSpeed);
        }
        if (StrUtil.isNotBlank(baseSpeedDto.getLinerSpeedY()) && Objects.equals(baseSpeedDto.getLinerSpeed(), "0")) {
            linerYSpeed = baseSpeedDto.getLinerSpeedY().contains("-") ? "-" + linerYSpeed : linerYSpeed;
            linerYSpeed = Objects.equals(baseSpeedDto.getLinerSpeedY(), "0") ? "0" : linerYSpeed;
            lineYResult = KcToolkit.writeVar("cmd_vel_line_y", DataTypeEnum.REAL, linerYSpeed);
            log.info("[kc] set line y speed {} m/s", linerYSpeed);
        }
        if (StrUtil.isNotBlank(baseSpeedDto.getAngularSpeed())) {
            //摇杆取值
            if (baseSpeedDto.isRocker()) {
                float webSpeed = Math.abs(Float.parseFloat(baseSpeedDto.getAngularSpeed()));
                angularSpeed = String.valueOf(Math.min(Float.parseFloat(angularSpeed), webSpeed));
            }
            //符号
            angularSpeed = baseSpeedDto.getAngularSpeed().contains("-") ? "-" + angularSpeed : angularSpeed;
            angleResult = KcToolkit.writeVar("cmd_vel_angle", DataTypeEnum.REAL, angularSpeed);
            log.info("[kc] set angle speed {} m/s", angularSpeed);
        }
        return lineXResult & lineYResult & angleResult;
    }

    @Override
    public boolean changeWebControlSpeed(float changeValue) {
        speed = Math.min(Math.max(speed + changeValue, minSpeed), maxSpeed);
        return true;
    }

    /**
     * 设置初始位置 （web下发的话要先调用canvas2Point再调这个接口）
     *
     * @param baseInitPosDto 激光坐标
     * @return true/false
     */
    @Override
    public boolean setInitPos(InitPosDto baseInitPosDto) {
        float posX = baseInitPosDto.getPosx();
        float posY = baseInitPosDto.getPosy();
        float posYaw = baseInitPosDto.getYaw();
        return KcToolkit.setInitPos(posX, posY, posYaw);
    }

    @Override
    public boolean robotTaskGoTarget(RobotGoTargetPosDto dto) {
        try {
            KcRobotRunningStatus runningStatus = (KcRobotRunningStatus) KcCacheUtil.get(KcCacheUtil.KEY_RUNNING_STATUS);
            if (runningStatus != null && Objects.equals(runningStatus.getRunMode(), 0)) {
                //切换自动模式
                KcToolkit.changeRunningMode(1);
                Thread.sleep(200);
            }
            if (runningStatus != null && runningStatus.getIsCharging() == 1) {
                log.info("[kc]充电中，取消充电");
                KcToolkit.writeVar("cmd_a_charge", DataTypeEnum.INT, String.valueOf(0));
            }
            KcToolkit.navToPosControl(1, "0");
            Thread.sleep(200);
            log.info("[kc]前往目标点: {}", dto.getCode());
            //保存目标点，用于恢复
            KcToolkit.targetPosCode = dto.getCode();
            return KcToolkit.navToPosControl(0, dto.getCode());
        } catch (Exception e) {
            log.info("[kc]前往目标点失败:{}", e.getMessage());
            return false;
        }
    }


    /**
     * 中断机器人的动作
     *
     * @return
     */
    @Override
    public boolean motionAbort() {
        KcToolkit.targetPosCode = "";
        return KcToolkit.navToPosControl(1, "0");
    }

    @Override
    public boolean navCmd(Integer cmd) {
        boolean result = false;
        if (CmdNavStatusEnum.NAV_PAUSE.getCode() == cmd) {
            result = KcToolkit.navToPosControl(2, "0");
            if (KcToolkit.isAutoCharge) {
                KcToolkit.isAutoCharge = false;
                log.info("[kc] 急停关闭自主充电标志位");
            }
        } else if (CmdNavStatusEnum.NAV_CANCEL.getCode() == cmd) {
            log.warn("[kc] 停止导航");
            result = KcToolkit.navToPosControl(1, "0");
        } else if (CmdNavStatusEnum.NAV_CONTINUE.getCode() == cmd) {
            result = KcToolkit.navToPosControl(3, "0");
        }
        return result;
    }

    @Override
    public boolean cmdCharge(Integer cmd) {
        return KcToolkit.writeVar("cmd_a_charge", DataTypeEnum.INT, String.valueOf(cmd));
    }

    @Override
    public R executeOtherCommand(RobotOtherCommandEnum cmdEnum, String jsonParams) {
        switch (cmdEnum) {
            case SET_DOOR_STATUS -> {
                DoorStatusDto cmdDoorDto = JSON.parseObject(jsonParams, DoorStatusDto.class);
                int sn = cmdDoorDto.getSn();
                int status = cmdDoorDto.getStatus();
                boolean async = cmdDoorDto.isAsync();
                if (status == 1) {
                    //开门
                    return M518Toolkit.openDoor() ? R.ok() : R.failed();
                }
                if (status == 0) {
                    //关门
                    return M518Toolkit.closeDoor() ? R.ok() : R.failed();
                }
            }
            case GO_HOME -> {
                if (goHomeLimiter.tryAcquire(6)) {
                    KcToolkit.navToPosControl(0, StrUtil.isBlank(KcToolkit.chargePosCode) ? "1" : KcToolkit.chargePosCode);
                    KcToolkit.writeVar("cmd_lift_pos", DataTypeEnum.REAL, "0");
                }
            }
            case RELOCATION -> {
                KcToolkit.writeVar("init_pose_cmd", DataTypeEnum.INT, "1");
                log.info("[kc]重定位");
            }
            case JACKING_UP -> {
                KcToolkit.readVar("rep_lift_get_mm");
                String height = KcCacheUtil.getVarCache("rep_lift_get_mm");
                if (StrUtil.isNotBlank(height)) {
                    int newHeight = Math.max(Math.min(Integer.parseInt(height) + 10, 480), 10);
                    KcToolkit.writeVar("cmd_lift_set_mm", DataTypeEnum.INT, String.valueOf(newHeight));
                    log.info("[kc]set jacking:{} -> {}", height, newHeight);
                }
            }
            case JACKING_DOWN -> {
                KcToolkit.readVar("rep_lift_get_mm");
                String height = KcCacheUtil.getVarCache("rep_lift_get_mm");
                if (StrUtil.isNotBlank(height)) {
                    int newHeight = Math.max(Math.min(Integer.parseInt(height) - 10, 480), 10);
                    KcToolkit.writeVar("cmd_lift_set_mm", DataTypeEnum.INT, String.valueOf(newHeight));
                    log.info("[kc]set jacking:{} -> {}", height, newHeight);
                }
            }
            case SET_JACKING -> {
                List<RobotParamsDto> robotParamsDtos = JSONObject.parseArray(jsonParams, RobotParamsDto.class);
                Optional<RobotParamsDto> heightDto = robotParamsDtos.stream().filter(t -> "height".equals(t.getKey())).findFirst();
                if (heightDto.isPresent()) {
                    int height = Integer.parseInt(heightDto.get().getValue());
                    int newHeight = Math.max(Math.min(height, 480), 10);
                    KcToolkit.writeVar("cmd_lift_set_mm", DataTypeEnum.INT, String.valueOf(newHeight));
                    log.info("[kc]set jacking:{}", newHeight);
                    for (int i = 0; i < 10; i++) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        String currentHeight = KcToolkit.readVar("rep_lift_get_mm");
                        if (StrUtil.isNotBlank(currentHeight) && Math.abs(Integer.parseInt(currentHeight) - newHeight) <= 2) {
                            log.info("[kc]升降杆到位");
                            break;
                        }
                    }
                }
            }
            case SET_JACKING_ORIGIN -> {
                KcToolkit.writeVar("cmd_lift_set_mm", DataTypeEnum.INT, "0");
            }
            case JACKING_STATUS -> {
                KcToolkit.readVar("rep_lift_get_mm");
                String height = KcCacheUtil.getVarCache("rep_lift_get_mm");
                log.info("[kc]current jacking: {}", height);
                int v = StrUtil.isBlank(height) ? 0 : Integer.parseInt(height);
                v =  Math.max(Math.min(v, 480), 10);
                List<RobotParamsDto> params = Lists.newArrayList();
                params.add(new RobotParamsDto("顶升高度(mm)", "height", String.valueOf(v), ""));
                return R.ok(params);
            }
        }
        return R.ok();
    }

    @Override
    public List<RobotCustomInfo> getCustomInfo() {
        List<RobotCustomInfo> customInfo = new ArrayList<>();
        for (Map.Entry<String, Object> entry : TasLan464Toolkit.cache.asMap().entrySet()) {
            customInfo.add(RobotCustomInfo.create(entry.getKey(), entry.getKey(), String.valueOf(entry.getValue())));
        }
        KcRobotRunningStatus runningStatus = (KcRobotRunningStatus) KcCacheUtil.get(KcCacheUtil.KEY_RUNNING_STATUS);
        if (runningStatus != null) {
            customInfo.add(RobotCustomInfo.create("laserPos", "激光坐标", "(" + df.format(runningStatus.getPositionX()) + "," + df.format(runningStatus.getPositionY()) + ")"));
            customInfo.add(RobotCustomInfo.create("angle", "转向角度", df.format(runningStatus.getOrientationAngle() * 180 / Math.PI) + "°"));
            if (KcToolkit.map != null && KcToolkit.map.getHeight() != null && KcToolkit.map.getWidth() != null) {
                PointDto pointDto = point2Canvas(KcToolkit.map, new PointDto(runningStatus.getPositionX(), runningStatus.getPositionY()));
                customInfo.add(RobotCustomInfo.create("pixelPos", "像素坐标", "(" + Double.valueOf(pointDto.getX()).intValue() + "," + Double.valueOf(pointDto.getY()).intValue() + ")"));
            }
            customInfo.add(RobotCustomInfo.create("confidence", "定位置信度", df.format(runningStatus.getConfidence())));
            customInfo.add(RobotCustomInfo.create("blocked", "避障状态", runningStatus.getIsBlocked() == 0 ? "未阻挡" : "阻挡"));
            KcStopStatusDto kcStopStatusDto = (KcStopStatusDto) KcCacheUtil.get(KcCacheUtil.KEY_STOP_STATUS);
            if (kcStopStatusDto != null) {
                customInfo.add(RobotCustomInfo.create("frontStopBarStatus", "前防撞条", kcStopStatusDto.getFrontStopBarStatus() == 0 ? "未触发" : "触发"));
                customInfo.add(RobotCustomInfo.create("backStopBarStatus", "后防撞条", kcStopStatusDto.getBackStopBarStatus() == 0 ? "未触发" : "触发"));
                customInfo.add(RobotCustomInfo.create("hardStopStatus", "硬急停", kcStopStatusDto.getHardStopStatus() == 0 ? "未触发" : "触发"));
            }
            KcLocationDto kcLocationDto = (KcLocationDto) KcCacheUtil.get(KcCacheUtil.KEY_LOCATION_STATUS);
            if (kcLocationDto != null) {
                customInfo.add(RobotCustomInfo.create("currentCode", "当前点", "距" + kcLocationDto.getCurrentCode() + "(" + kcLocationDto.getDistance() + "m)"));
            }
            customInfo.add(RobotCustomInfo.create("targetPointId", "目标点", String.valueOf(runningStatus.getTargetPointId())));
            customInfo.add(RobotCustomInfo.create("taskStatus", "队列状态", KcNavStatusEnum.getDes(runningStatus.getTaskStatus())));
            customInfo.add(RobotCustomInfo.create("webSpeed", "手动速度", df.format(speed) + "m/s"));
            customInfo.add(RobotCustomInfo.create("robotPositionStatus", "定位状态", KcPositionStatusEnum.getDes(runningStatus.getRobotPositionStatus())));
            customInfo.add(RobotCustomInfo.create("totalMileage", "累计里程", Double.valueOf(runningStatus.getTotalMileage()).intValue() + "m"));
            customInfo.add(RobotCustomInfo.create("currentMapName", "当前地图编码", runningStatus.getCurrentMapName()));
        }
        String repBmsProtectStr = KcCacheUtil.getVarCache("rep_BMS_Protect_str");
        if (StrUtil.isNotBlank(repBmsProtectStr)) {
            customInfo.add(RobotCustomInfo.create("BMS", "BMS状态", repBmsProtectStr));
        }

        // 气体检测
        String repC3h10Si = KcCacheUtil.getVarCache("repC3h10Si");
        if (StrUtil.isNotBlank(repC3h10Si)) {
            customInfo.add(RobotCustomInfo.create("repC3h10Si", "三甲基硅烷", repC3h10Si + "ppm"));
        }
        String repH2 = KcCacheUtil.getVarCache("repH2");
        if (StrUtil.isNotBlank(repH2)) {
            customInfo.add(RobotCustomInfo.create("repH2", "氢气", repH2 + "ppm"));
        }
        String repC3h6 = KcCacheUtil.getVarCache("repC3h6");
        if (StrUtil.isNotBlank(repC3h6)) {
            customInfo.add(RobotCustomInfo.create("repC3h6", "丙烯", repC3h6 + "ppm"));
        }
        String repTemp = KcCacheUtil.getVarCache("repTemp");
        if (StrUtil.isNotBlank(repTemp)) {
            float tempFloat = Float.parseFloat(repTemp) / 10;
            customInfo.add(RobotCustomInfo.create("repTemp", "温度", df_2.format(tempFloat) + "℃"));
        }
        String repHumidity = KcCacheUtil.getVarCache("repHumidity");
        if (StrUtil.isNotBlank(repHumidity)) {
            float repHumidityFloat = Float.parseFloat(repHumidity) / 10;
            customInfo.add(RobotCustomInfo.create("repHumidity", "湿度", df_2.format(repHumidityFloat) + "%"));
        }

        return customInfo;
    }

    /**
     * 获取地图显示坐标
     *
     * @return
     */
    @Override
    public IRobotPosDto getWebPos() {
        KcRobotRunningStatus runningStatus = (KcRobotRunningStatus) KcCacheUtil.get(KcCacheUtil.KEY_RUNNING_STATUS);
        if (runningStatus == null) {
            runningStatus = new KcRobotRunningStatus();
        }
        IRobotPosDto iRobotPosDto = KcRobotRunningStatus.getIRobotPosDto(runningStatus);
        iRobotPosDto.setUrl(Optional.ofNullable(KcToolkit.map).map(RobotMap::getFilePath).orElse(""));
        iRobotPosDto.setCurrentMap(Optional.ofNullable(KcToolkit.map).map(RobotMap::getMapCode).orElse(""));
        iRobotPosDto.setWebControlSpeed(speed);
        iRobotPosDto.setCurrentDirection(runningStatus.getIsCharging() == 0 ? "放电" : "充电");
        //坐标转换
        try {
            if (KcToolkit.map != null && KcToolkit.map.getHeight() != null && KcToolkit.map.getWidth() != null) {
                PointDto pointDto = point2Canvas(KcToolkit.map, new PointDto(iRobotPosDto.getX(), iRobotPosDto.getY()));
                iRobotPosDto.setPixelX(Double.valueOf(pointDto.getX()).intValue());
                iRobotPosDto.setPixelY(Double.valueOf(pointDto.getY()).intValue());
                iRobotPosDto.setPixelAngle(iRobotPosDto.getAngle());
            }
            // TODO: 形式过的路径
            ArrayList<PointDto> pointDtos = new ArrayList<>();
            iRobotPosDto.setQrCodeX(KcCacheUtil.getVarCache("rep_Cam_X"));
            iRobotPosDto.setQrCodeY(KcCacheUtil.getVarCache("rep_Cam_Y"));
            iRobotPosDto.setQrCodeZ(KcCacheUtil.getVarCache("rep_Cam_Z"));
            iRobotPosDto.setPassedPath(pointDtos);
        } catch (Exception e) {
            log.warn("[kc]坐标转换错误", e);
        }
        //导航信息
        KcLocationDto kcLocationDto = Optional.ofNullable((KcLocationDto) KcCacheUtil.get(KcCacheUtil.KEY_LOCATION_STATUS)).orElse(new KcLocationDto());
        iRobotPosDto.setReached(kcLocationDto.getIsReach() != null && kcLocationDto.getIsReach());
        iRobotPosDto.setCurrentStation(Optional.ofNullable(kcLocationDto.getCurrentCode()).orElse(""));
        //急停状态
        KcStopStatusDto kcStopStatusDto = Optional.ofNullable((KcStopStatusDto) KcCacheUtil.get(KcCacheUtil.KEY_STOP_STATUS)).orElse(new KcStopStatusDto());
//        boolean isEmergency = kcStopStatusDto.getHardStopStatus() == 1
//                || kcStopStatusDto.getBackStopBarStatus() == 1
//                || kcStopStatusDto.getFrontStopBarStatus() == 1;
        boolean isEmergency = kcStopStatusDto.getHardStopStatus() == 1;
        iRobotPosDto.setEmergency(isEmergency);
        return iRobotPosDto;
    }

    /**
     * 获取路径   注：科聪使用不指定路径方式导航，只要下发目的，让控制器自己规划就好
     *
     * @param sourcePos      起点点位
     * @param targetPos      目标点位
     * @param allRobotMapPos 所有地图点
     * @return 路径点位列表
     */
    @Override
    public List<RobotMapPos> getNavPath(RobotMapPos sourcePos, RobotMapPos targetPos, List<RobotMapPos> allRobotMapPos) {
        List<RobotMapPos> robotMapPosList = new ArrayList<>();
        robotMapPosList.add(targetPos);
        return robotMapPosList;
    }

    @Override
    public List<RobotMapPos> getRobotMapPos(String mapCode) {
        List<RobotMapPos> list = KcToolkit.parsePosInfo();
        if (list == null || list.isEmpty()) {
            return List.of();
        }
        return list;
    }

    @Override
    public List<RobotMap> getMapList() {
        RobotMap robotMap = KcToolkit.parseMapInfo();
        if (robotMap == null) {
            return List.of();
        }
        return List.of(robotMap);
    }

    @Override
    public String getCurrentMap() {
        KcRobotRunningStatus kcRobotRunningStatus = KcToolkit.queryRunningStatus();
        return kcRobotRunningStatus.getCurrentMapName();
    }

    @Override
    public MapAttributesDto getMapAttributes(String mapCode) {
        RobotMap robotMap = KcToolkit.parseMapInfo();
        if (robotMap == null) {
            return null;
        }
        MapAttributesDto dto = new MapAttributesDto();
        dto.setCurrentMapName(robotMap.getMapCode());
        dto.setMapOriginx(robotMap.getMapOriginx());
        dto.setMapOriginy(robotMap.getMapOriginy());
        dto.setMapResolution(robotMap.getMapResolution());
        return dto;
    }

    @Override
    public void selMap(RobotMap map) {
        KcToolkit.map = map;//287   293
        KcToolkit.posMap = map.getPosList().stream().collect(Collectors.toMap(RobotMapPos::getCode, pos -> pos));
    }

    @Override
    public PointDto canvas2Point(RobotMap robotMap, PointDto pointDto) {
        return null;
    }

    @Override
    public FormConfigDto getRobotConfig(String formName) {
        // 创建字段配置
        ArrayList<FormFieldConfigDto> fields = new ArrayList<>();
        //充电房
        fields.add(RobotParamsFormFieldEnum.CHARGE_POS_CODE.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.CHARGE_HOME_INSIDE_DOOR_POS_CODE.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.CHARGE_HOME_OUTSIDE_DOOR_POS_CODE.toConfigDto());
        //语音播报
        fields.add(RobotParamsFormFieldEnum.HK_VOICE_PLAY_ENABLE.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.HK_VOICE_PLAY_IP.toConfigDto());
        // 464模块配置 读气体传感器
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_IP.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM1_PORT.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM1_NAME.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM1_MESSAGE_TEXT.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM1_BRAND.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM2_PORT.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM2_NAME.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM2_MESSAGE_TEXT.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM2_BRAND.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM3_PORT.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM3_NAME.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM3_MESSAGE_TEXT.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM3_BRAND.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM4_PORT.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM4_NAME.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM4_MESSAGE_TEXT.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.TAS_LAN_464_COM4_BRAND.toConfigDto());
        // 开门器
        fields.add(RobotParamsFormFieldEnum.M518R_COM_NAME.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.M518R_COM_OPEN_MESSAGE_TEXT.toConfigDto());
        fields.add(RobotParamsFormFieldEnum.M518R_COM_CLOSE_MESSAGE_TEXT.toConfigDto());
        // 通过 FormConfigEnum 创建表单配置
        return FormConfigEnum.ROBOT_PARAMS_CONFIG.toFormConfigDto(fields);
    }

    @Override
    public RobotDriverEnum getDriverVersion() {
        return RobotDriverEnum.KC;
    }

    @Override
    public PointDto point2Canvas(RobotMap robotMap, PointDto pointDto) {
        PointDto pixelPoint = new PointDto();
        pixelPoint.setX((pointDto.getX() - robotMap.getMinX()) * robotMap.getWidth() / (robotMap.getMaxX() - robotMap.getMinX()));
        pixelPoint.setY((robotMap.getMaxY() - pointDto.getY()) * robotMap.getHeight() / (robotMap.getMaxY() - robotMap.getMinY()));
        return pixelPoint;
    }


}
